<?php

  abstract class BCMath
  {
    /**
     * Add two arbitrary precision numbers.
     * Sums the $left operand and the $right operand.
     *
     * @param Float $left The left operand.
     * @param Float $right The right operand.
     * @param Integer $scale This parameter is used to set the number of digits after the decimal place in the result.
     * @return Float The sum of the two operands.<br /><br />
     * @link http://be.php.net/manual/en/function.bcadd.php
     */
    public function Add(IFloat $left, IFloat $right, IInteger $scale = null) {
      if ($scale == null) {
        return new Float(floatval(bcadd($left->floatValue(), $right->floatValue(), 2)));
      } else {
        return new Float(floatval(bcadd($left->floatValue(), $right->floatValue(), $scale->integerValue())));
      }
    }

    /**
     * Compare two arbitrary precision numbers.
     * Compares the $left operand to the $right operand and returns the result.
     *
     * @param Float $left The left operand.
     * @param Float $right The right operand.
     * @param Float $scale The scale  parameter is used to set the number of digits after the decimal place which will be used in the comparison.
     * @return Integer 0 if the two operands are equal, 1 if the $left is larger than the $right and * -1 otherwise.
     * @link http://be.php.net/manual/en/function.bccomp.php
     */
    public function Compare(Float $left, Float $right, Integer $scale = null) {
      if ($scale == null) {
        return new Integer(intval(bccomp($left->floatValue(), $right->floatValue(), 2)));
      } else {
        return new Integer(intval(bccomp($left->floatValue(), $right->floatValue(), $scale->integerValue())));
      }
    }

    /**
     * Divide two arbitrary precision numbers.
     * Divides the $left operand by the $right operand.
     *
     * @param Float $left The left operand.
     * @param Float $right The right operand.
     * @param Float $scale This parameter is used to set the number of digits after the decimal place in the result.
     * @return Float The result of the division, or NULL if $right is 0.
     * @link http://be.php.net/manual/en/function.bcdiv.php
     */
    public function Divide(Float $left, Float $right, Integer $scale = null) {
      if ($scale == null) {
        return new Float(floatval(bcdiv($left->floatValue(), $right->floatValue(), 2)));
      } else {
        return new Float(floatval(bcdiv($left->floatValue(), $right->floatValue(), $scale->integerValue())));
      }
    }

    /**
     * Get modulus of an arbitrary precision number.
     * Get the modulus of the left_operand using modulus.
     *
     * @param Float $operand The left operand.
     * @param Float $modulus The modulus.
     * @return Float The modulus, or NULL if modulus is 0.
     * @link http://be.php.net/manual/en/function.bcmod.php
     */
    public function Modulo(Float $operand, Float $modulus) {
        return new Float(floatval(bcmod($operand, $modulus)));
    }

    /**
     * Multiply two arbitrary precision number.
     * Multiply the $left operand by the $right operand.
     *
     * @param Float $left The left operand.
     * @param Float $right The right operand.
     * @param Float $scale This parameter is used to set the number of digits after the decimal place in the result.
     * @return Float The result.
     * @link http://be.php.net/manual/en/function.bcmul.php
     */
    public function Multiply(Float $left, Float $right, Integer $scale = null) {
      if ($scale == null) {
        return new Float(floatval(bcmul($left->floatValue(), $right->floatValue(), 2)));
      } else {
        return new Float(floatval(bcmul($left->floatValue(), $right->floatValue(), $scale->integerValue())));
      }
    }

    /**
     * Raise an arbitrary precision number to another.
     * Raise $operand to the $power.
     *
     * @param Float $left The left operand.
     * @param Float $right The right operand.
     * @param Float $scale This parameter is used to set the number of digits after the decimal place in the result.
     * @return Float The result.
     * @link http://be.php.net/manual/en/function.bcpow.php
     */
    public function Power(Float $operand, Float $power, Integer $scale = null) {
      var_dump(bcpow($operand->floatValue(), $power->floatValue(), 2));
      if ($scale == null) {
        return new Float(floatval(bcpow($operand->floatValue(), $power->floatValue(), 2)));
      } else {
        return new Float(floatval(bcpow($operand->floatValue(), $power->floatValue(), $scale->integerValue())));
      }
    }

    /**
     * Get the square root of an arbitrary precision number.
     *
     * @param Float $operand The operand.
     * @param Float $scale This parameter is used to set the number of digits after the decimal place in the result.
     * @return Float The square root, or NULL if $operand is negative.
     * @link http://be.php.net/manual/en/function.bcsqrt.php
     */
    public function Sqrt(Float $operand, Integer $scale = null) {
      if ($scale == null) {
        return new Float(floatval(bcsqrt($operand->floatValue(), 2)));
      } else {
        return new Float(floatval(bcsqrt($operand->floatValue(), $scale->integerValue())));
      }
    }

    /** @see Sqrt() */
    public function SquareRoot(Float $operand, Integer $scale = null) {
      return BCMath::Sqrt($operand, $scale);
    }

    /**
     * Subtract one arbitrary precision number from another.
     * Subtracts the $right operand from the $left operand.
     *
     * @param Float $left The left operand.
     * @param Float $right The right operand.
     * @param Float $scale This parameter is used to set the number of digits after the decimal place in the result.
     * @return Float The result of the substraction, as a string.
     * @link http://be.php.net/manual/en/function.bcsub.php
     */
    public function Substract(Float $left, Float $right, Integer $scale = null) {
      if ($scale == null) {
        return new Float(floatval(bcsub($left->floatValue(), $right->floatValue(), 2)));
      } else {
        return new Float(floatval(bcsub($left->floatValue(), $right->floatValue(), $scale->integerValue())));
      }
    }
  }
?>
